// #include <pthread.h>
// #include <iostream>
// #include <errno.h>
// #include <string.h>
// #include <unistd.h>
// #include <time.h>
// #include <vector>
// #include <thread>
// #include "Thread.hpp"

// using namespace std;

// //模拟买票
// int g_tickets = 10000; // 共享资源，没有保护的S

// class ThreadData
// {
// public:
//     ThreadData(string& name, int total, int& _tickets)
//     :_name(name), _total(total), _tickets(_tickets)
//     {}
//     ~ThreadData()
//     {}
// public:
//     string _name;
//     int _total;
//     int& _tickets;
// };
// void route(ThreadData* td)
// {
//     while (true)
//     {
//         if(td->_tickets > 0)    //可能tickets==1，判断时，多个线程同时进入抢票逻辑
//         {
//             usleep(1000);
//             printf("%s get tickets: %d\n", td->_name.c_str() , td ->_tickets);
//             td->_tickets--; //执行多线程时，其中一个线程执行完--后将数据写回内存，其他的线程访问到的是写回后的数据
//                             //共享资源被访问时，没有被保护，
//             td->_total++;
//         }
//         else
//         {
//             break;
//         }
//     }
// }

// const int num = 4;
// int main()
// {
//     // std::cout << "main： &tickets: " << &g_tickets << std::endl;

//     vector<ThreadModule::Thread<ThreadData*>> threads;
//     vector<ThreadData *> datas;
//     // 1. 创建一批线程
//     for (int i = 0; i < num; i++)
//     {
//         std::string name = "thread-" + std::to_string(i + 1);
//         ThreadData* td = new ThreadData(name, 0, g_tickets);
//         threads.emplace_back(route, td, name);
//         datas.emplace_back(td);
//     }

//     // 2. 启动 一批线程
//     for (auto &thread : threads)
//     {
//         thread.Start();
//     }

//     // 3. 等待一批线程
//     for (auto& thread : threads)
//     {
//         thread.Join();
//         //std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
//     }

//     //4.查看每个线程的抢票情况
//     for (auto td : datas)
//     {
//         printf("%s : tickets %d\n", td->_name.c_str (), td->_total);
//         delete td;
//     }

//     return 0;
// }





// void Print(int num)
// {
//     while (num--)
//     {
//         cout << "I am  "<< pthread_self() << " , num : " << num << endl;
//         sleep(1);
//     }
// }

// const int num = 5;
// int main()
// {
//     std::vector<ThreadModule::Thread<int>> thread_vec;
//     //1.创建一批线程
//     for (int i = 0; i < num; i++)
//     {
//         thread_vec.emplace_back(Print, 5, string("thread-") + to_string(i+1));
//     }

//     //2.启动一批线程
//     for (auto& t: thread_vec)
//     {
//         t.Start();
//     }

//     //3.等待一批线程
//     for (auto& t : thread_vec)
//     {
//         t.Join();
//     }
// }





// void Print(int& num)
// {
//     while (num--)
//     {
//         cout << "I am new thread, num : " << num << endl;
//         sleep(1);
//     }
// }
// int main()
// {
//     ThreadModule::Thread<int> t1(Print, 5);
//     t1.Start();
//     while (true)
//     {
//         sleep(1);
//     }
//     //t1.Join();
//     t1.Detach();
// }







// int g_val = 10; //进程定义的全局变量，默认是所有线程都可以看见的 -- 线程共享地址空间
// __thread uint64_t starttime;   //__thread修饰的全局变量，会被存储到动态库中的线程局部存储，不同的线程看到的不一样

// void *threadrun1(void *arg)
// {
//     starttime = time(nullptr);
//     string name = static_cast<char *>(arg);
//     int cnt = 5;
//     while (cnt--)
//     {
//         cout << "I am " << name << ", cnt : " << cnt << ", &cnt : " << &cnt << endl;
//         cout << "g_val : " << g_val << "&g_val : " << &g_val << endl;
//         cout << "starttime :" << starttime << endl;
//         sleep(1);
//     }
//     // pthread_detach(pthread_self()); //自己分离自己
//     // cout << "I am a new thread" << endl;

//     return nullptr;
// }

// void *threadrun2(void *arg)
// {
//     starttime = time(nullptr);
//     string name = static_cast<char*>(arg);
//     int cnt = 5; // 定义在私有栈上
//     while (cnt--)
//     {
//         sleep(1);
//         cout << "I am " << name << ", cnt : " << cnt << ", &cnt : " << &cnt << endl;
//         cout << "g_val : " << g_val << "&g_val : " << &g_val << endl;
//         cout << "starttime : " << starttime << endl;
//     }
//     return nullptr;
// }
// // 线程可以分离；线程默认是joinable，需要等待，分离后的线程不需要主线程等待，会自动释放
// // main thread不需要获取new thread的返回数据时，可以将新线程分离，新线程执行完后，会由OS帮我们释放。
// // 线程分离时，底层仍然属于同一个进程，只是不要等待分离的线程了
// //  a.任意一个线程收到信号，所有线程都会退出
// //  b.主线程退出后，所有线程都会退出
// // 一般希望主线程是最后一个退出的
// int main()
// {
//     pthread_t tid1 = 0, tid2 = 0;
//     pthread_create(&tid1, nullptr, threadrun1, (char *)"thread-1");
//     sleep(5);
//     pthread_create(&tid2, nullptr, threadrun2, (char *)"thread-2");

//     int cnt = 5;

//     while (cnt--)
//     {
//         cout << "I am a main thread" << endl;
//         sleep(1);
//     }

//     cout << "main thread wait block" << endl;
//     int n = pthread_join(tid1, nullptr);
//     n = pthread_join(tid2, nullptr);
//     cout << "main thread wait return" << endl;
//     cout << "n : " << n << ", errstr: " << strerror(n) << endl;
// }

// #include <iostream>
// #include <thread>   //C++中的线程，本质封装了Linux的线程库；实现了线程编程的跨平台性
// #include <unistd.h>
// using namespace std;

// void threadRun(int num)
// {
//     cout << "I am a new thread, num : " << num << endl;
//     sleep(1);
// }
// int main()
// {
//     thread t1(threadRun, 1);
//     thread t2(threadRun, 1);
//     thread t3(threadRun, 1);
//     thread t4(threadRun, 1);
//     thread t5(threadRun, 1);

//     while (true)
//     {
//         cout << "I am a main thread " << endl;
//         sleep(1);
//     }

//     t1.join();
//     t2.join();
//     t3.join();
//     t4.join();
//     t5.join();
// }

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdlib>
#include <sys/types.h>
#include <cstdio>
#include <vector>
using namespace std;
int thread_num = 5;

class Task
{
public:
    Task(int x, int y)
    :_x(x)
    ,_y(y)
    {}
    ~Task()
    {}
    int Excute()
    {
        return _x + _y;
    }
private:
    int _x;
    int _y;
};

class ThreadData
{
public:
    ThreadData(const string& name, Task t)
    :_threadname(name)
    ,_t(t)
    {}
    ~ThreadData()
    {}

    int run()
    {
        return _t.Excute();
    }
    string name()
    {
        return _threadname;
    }
private:
    string _threadname; //线程名
    Task _t;    //线程要完成的任务
};

class Result
{
public:
    Result()
    {}
    ~Result()
    {}
    void SetResult(int res, string name)
    {
        _res = res;
        _threadname = name;
    }
    void Print()
    {
        cout << "thread " << _threadname << " run result : " << _res << endl;
    }
private:
    int _res;
    string _threadname;
};
void *handleTask(void *arg)
{
    //string name = static_cast<char *>(arg);
    ThreadData* td_ptr = static_cast<ThreadData*>(arg);
    string threadname = td_ptr->name();
    int res = td_ptr->run();
    Result* res_ptr = new Result();
    res_ptr->SetResult(res, threadname);
    cout << td_ptr->name() << " run result : " << td_ptr->run() <<  endl;

    delete td_ptr;
    sleep(2);
    return res_ptr;
}
// 1.创建多线程
// 2.线程传参和返回值，我们可以传递级别信息，也可以传递对象
int main()    
{
    vector<pthread_t>threads;
    for (int i = 0; i < thread_num; i++)                    
    {
        char threadname[64]; //每个线程不能共享数据(否则其中一个线程数据会被其他的线程覆盖)，应该独享
        //char* threadname  = new char[64];   //应该这么写
        snprintf(threadname, 64, "thread-%d", i + 1);

        ThreadData* td_ptr = new ThreadData(threadname, Task(10, 20));  //参数传递ThreadData类

        pthread_t tid = 0;
        pthread_create(&tid, nullptr, handleTask, td_ptr);
        threads.push_back(tid);
    }
    vector<Result*> res_vector;
    void* res = nullptr;
    for (auto &tid : threads)
    {
        pthread_join(tid, &res);
        res_vector.push_back((Result*)res);
    }

    for (auto & res : res_vector)
    {
        res->Print();
        delete res;
    }
}

// // 同一个进程内的线程，大部分的资源是共享的，地址空间是共享

// string ToHex(pthread_t tid)
// {
//     char buf[64];
//     snprintf(buf, sizeof(buf), "0x%lx", tid);
//     return buf;
// }

// int g_val = 10;

// // 线程退出
// // 1.代码跑完，结果正确
// // 2.代码跑完，结果不正确
// // 3.出现异常 -- 重点 -- 多线程中，任何一个线程出现异常，会让整个进程退出！ 多线程代码的健壮性不好
// void *CreatThread(void *arg)
// {
//     string tname = (char *)arg;
//     int cnt = 5;
//     while (cnt)
//     {
//         printf("new thread , g_val is %d, &g_val is %p\n", g_val, &g_val);
//         // cout << tname << " ia a new thread, pid: " << getpid()
//         // << ", cnt: " << cnt
//         // << endl;
//         cnt--;
//         g_val++;
//         sleep(1);
//         // //模拟异常
//         // int*p = nullptr;
//         // *p = 100;
//     }
//     //1.线程函数结束
//     return (void *)123; // 退出码

//     //2.线程提前终止
//     //pthread_exit((void*)123);
//     //exit(10); //不能用exit，exit是终止整个进程的
// }
// // 主线程退出==进程退出==所有的线程退出

// //  1.往往我们需要main thread最后结束
// //  2.线程也需要“wait”，不然会出现内存泄漏的问题
// int main()
// {
//     pthread_t tid;
//     // tid是新线程的id，用在库函数中标识唯一线程；LWD是内核中用于唯一标识线程的
//     pthread_create(&tid, nullptr, CreatThread, (char *)"thread-1");

//     // while (true)
//     // {
//     //     printf("main thread, g_val is %d, &g_val is %p\n", g_val, &g_val);
//     //     sleep(1);
//     // }

//     //3. 主线程取消新线程
//     //PTHREAD_CANCELED;   //(void*)-1
//     //pthread_cancel(tid);

//     // 阻塞等待新线程退出并接受退出码
//     void *ret = nullptr;
//     int n = pthread_join(tid, &ret);
//     //sleep(5);
//     cout << "new thread quit, n:" << n << ", ret: " << (long long)ret << endl;
//     while (true) sleep(1);
//     // //新线程和主线程谁先执行？不确定，由调度器决定
//     // while (true)
//     // {
//     //     cout << "I am a main thread, pid: " << getpid()
//     //     << ", main thread id: " << ToHex(pthread_self())
//     //     << ", new thread id: " << ToHex(tid)
//     //     << endl;
//     //     sleep(1);
//     // }

//     return 0;
// }